/*
 * CS_REQ_FAIRY_GACHYA.cpp
 *
 *  Created on: 2013. 7. 22.
 *      Author: mega@gamevil.com
 */

#include "../../Command.h"
#include "../../User.h"
#include "../../Enum.h"
#include "../../NResource/Static.h"
#include "../../NUtil/Utils.h"
#include "../../NLogic/Item.h"
#include "../../NLogic/Bag.h"
#include "../../NLogic/MailBox.h"
#include "../../NLogic/Static.h"
#include "../../NLogic/VirtualCurrency.h"

namespace ProjectZ { namespace NCommand {

void SendFailFairyGachya(User * pUser, int res)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(res);
	*pAck << static_cast<uint8_t>(0);
	pAck->MakePacket(CMD_SC_REQ_FAIRY_GACHYA);
	pUser->Send(pAck);
	return;
}

void Command::CS_REQ_FAIRY_GACHYA(User * pUser, ::Network::Packet * pPacket)
{
/*	CS_REQ_FAIRY_GACHYA 0x01508
	{
		u8 	u8count;			// 뽑기 갯수
		u8  u8gachyaType		// 페어리 뽑기 타입       0 : 일일뽑기, 1 : 인벤 뽑기, 2 : 샵 뽑기 (페어리 팩), 3: 메일에서 뽑기
		u8	u8PetEggQuality		// 클라이언트 요청 레벨   0 : 일일뽑기, 1 : 2성이상, 2 : 3성이상
		u64 u64seq;				// 샵 뽑기인 경우에는 유료 아이템 Seq, 메일 뽑기 인 경우에는 메일 Seq, 그 외에는 0
	}

	SC_REQ_FAIRY_GACHYA 0x01509
	{
		s16	u16ack;

		u8	u8count
		{
			u8	u8FairyEggRank;			// 페어리알 등급 ( 연출용 )
			u64	item_seq;
		}
	}*/

	PREPARE_PACKET;

	uint8_t gachyaCount = 0;
	uint8_t gachyaQuality = 0;
	uint8_t gachyaType = 0;
	uint64_t seq = 0;

	*pPacket >> gachyaCount >> gachyaType >> gachyaQuality >> seq;

	NLogic::Bag * pBag = pUser->GetBag(BAG_TYPE_FAIRY);
	if (pBag == NULL)
	{
		SendFailFairyGachya(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	// 마을입장전에 샵에서 페어리팩을 구매하는 경우가 있으므로, 아이템이 로딩되어 있지 않다면 로딩한다
	if (false == pBag->IsLoad())
	{
		if (false == pBag->ItemLoadFromDatabase())
		{
			DEBUGLOG("CS_REQ_FAIRY_GACHYA : ITEMLOADFROMDATABASE FAIL GID : %d", pUser->GetUserSeq());
			return;
		}
	}

	if (gachyaCount <= 0 || gachyaCount > 5)
	{
		SendFailFairyGachya(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	if (gachyaQuality < 0 || gachyaQuality > 2)
	{
		SendFailFairyGachya(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	if (gachyaType < 0 || gachyaType > 3)
	{
		SendFailFairyGachya(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	// 샵에서 구매했거나, 메일에서 뽑는 경우 seq는 반드시 0이상이어야 한다
	if (2 == gachyaType || 3 == gachyaType)
	{
		if (0 >= seq)
		{
			SendFailFairyGachya(pUser, ACK_UNKNOWN_ERROR);
			return;
		}
	}

	int vcIndex = 0;
//	int eggTid = 0;
//	int eggSheetType = 0;

	NLogic::MailBox::Mail * pMail = NULL;

	// 인벤토리에서 페어리 뽑기인 경우. 보유 ZEN 확인
	if (1 == gachyaType)
	{
		vcIndex = static_cast<int>(EM_VCINDEX_FAIRY_GACHYA);

		NResource::VCResource::Flyweight * pVCFly =
				NResource::Static::InstancePtr()->GetVCRef()->GetFly(vcIndex);

		if (NULL == pVCFly)
		{
			DEBUGLOG("CS_REQ_FAIRY_GACHYA : pVCFly is NULL!! vcindex=%d", vcIndex);
			return;
		}

		if (pUser->GetVirtualCurrency()->GetZen() < (pVCFly->_VC_PRICE * gachyaCount * -1))
		{
			SendFailFairyGachya(pUser, ACK_NOT_ENOUGH_ZEN);
			return;
		}
	}
	// 샵에서 구매한 페어리 팩으로 뽑기인 경우. 보유 ZEN 확인
	else if (2 == gachyaType)
	{
		NResource::ChargeItemData::Flyweight * pFly =
				NResource::Static::InstancePtr()->GetChargeItem()->GetFly(pUser, seq);

		if (pFly == NULL)
		{
			DEBUGLOG("CS_REQ_FAIRY_GACHYA : pFly is NULL!!! chargeSeq=%d", seq);
			SendFailFairyGachya(pUser, ACK_UNKNOWN_ERROR);
			return;
		}

		vcIndex = pFly->_VC_INDEX;
//		eggTid = pFly->_TID;
//		eggSheetType = pFly->_SHEET;

		NResource::VCResource::Flyweight * pVCFly =
				NResource::Static::InstancePtr()->GetVCRef()->GetFly(vcIndex);

		if (NULL == pVCFly)
		{
			DEBUGLOG("CS_REQ_FAIRY_GACHYA : pVCFly is NULL!! vcindex=%d", vcIndex);
			return;
		}

		if (pUser->GetVirtualCurrency()->GetZen() < (pVCFly->_VC_PRICE * -1))
		{
			SendFailFairyGachya(pUser, ACK_NOT_ENOUGH_ZEN);
			return;
		}
	}
	// 메일에서 뽑기인 경우 메일이 존재하는지 먼저 확인한다
	else if (3 == gachyaType)
	{
		if (NULL == pUser->GetMailBox())
		{
			DEBUGLOG("CS_REQ_FAIRY_GACHYA : MailBox is NULL!!");
			return;
		}

		pMail = pUser->GetMailBox()->GetMailData(seq);
		if (NULL == pMail)
		{
			DEBUGLOG("CS_REQ_FAIRY_GACHYA : pMail is NULL!!");
			return;
		}

		// 아이템이 첨부된 메일이 아닌 경우
		if (EM_GIFT_ITEM != (pMail->GetData().gift_status & EM_GIFT_ITEM))
		{
			DEBUGLOG("CS_REQ_FAIRY_GACHYA : Not Found Item in Mail");
			return;
		}

		// 요청 갯수와 메일의 첨부 아이템 갯수 확인
		if (pMail->GetData().item.quantity != gachyaCount)
		{
			DEBUGLOG("CS_REQ_FAIRY_GACHYA : Request Count MisMatch!!");
			return;
		}
	}

	// 인벤의 공간이 모자란 경우
	if (gachyaCount > pBag->RemainBagSlotCount())
	{
//		// 샵에서 페어리 팩을 구매한 경우 인벤토리 공간이 부족하면 메일 발송
//		if (2 == gachyaType)
//		{
//			NLogic::MailBox::Mail::Data clsMailData;
//			clsMailData.send_user_seq		= 0;
//			clsMailData.send_user_nickname	= "GAMEVIL";
//			clsMailData.recv_user_seq		= pUser->GetUserInfo().userseq;
//			clsMailData.message				= NResource::Static::InstancePtr()->GetMailMessageResource()->GetMessageFairyPackage();
//			clsMailData.gift_status			= EM_GIFT_ITEM;
//			clsMailData.item.tid			= eggTid;
//			clsMailData.item.sub_type		= eggSheetType;
//			clsMailData.item.class_type		= -1;
//			clsMailData.item.quantity		= gachyaCount;
//			NResource::Static::InstancePtr()->GetItemResource()->SetItemDataFromResource(pUser, clsMailData.item);
//
//			if (false == NLogic::NFunction::SendMail(pUser, clsMailData))
//			{
//				DEBUGLOG("CS_REQ_FAIRY_GACHYA : false == NLogic::NFunction::SendMail");
//				return;
//			}
//
//			// 메일 발송 후 VC 처리
//			NLogic::NFunction::VCProcess(pUser, vcIndex);
//
//			SendFailFairyGachya(pUser, ACK_INVEN_FULL_SEND_MAIL);
//			return;
//		}

		SendFailFairyGachya(pUser, ACK_INVEN_BAG_FULL);
		return;
	}

	// 페어리 뽑기 실행
	int prevFairyType = -1;
	std::vector< NLogic::Item * > clsItemVector;

	for (int i = 0; i < gachyaCount; i++)
	{
		NLogic::Item::Data clsData;

		if (false == NResource::Static::InstancePtr()->GetFairyGachya()->FairyGachya(pUser, clsData, prevFairyType, gachyaQuality))
			break;

		bool bBagFull = false;
		NLogic::Item * pItem = pBag->AddItemWithData(clsData, bBagFull);
		if (NULL == pItem)
			break;

		clsItemVector.push_back(pItem);

		prevFairyType = clsData.eff_type[0];
	}

	// 요청 만큼 페어리 뽑기가 성공 했는지 여부를 확인 하고, 실패인 경우 이미 인벤에 들어가 있는 아이템 삭제
	int successCount = static_cast<int>(clsItemVector.size());
	if (successCount < gachyaCount)
	{
		// 이미 인벤에 들어가 있는 아이템 삭제
		for (int i = 0; i < successCount; i++)
		{
			NLogic::Item * pItem = clsItemVector[i];
			pBag->PopItem(pItem->GetItemSeq());
			pItem->DeleteDatabaseItemInfo(NLogic::Item::ItemStatus::EM_ITEM_STATUS_INVALID_ITEM);
		}

		DEBUGLOG("CS_REQ_FAIRY_GACHYA : GAHCYA FAIL!! successCount=%d, gachyaCount=%d", successCount, gachyaCount);
		SendFailFairyGachya(pUser, ACK_UNKNOWN_ERROR);
		return;
	}

	// 응답
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();
	*pAck << static_cast<int16_t>(ACK_OK);
	*pAck << gachyaCount;

	for (int i = 0; i < gachyaCount; i++)
	{
		NLogic::Item * pItem = clsItemVector[i];
		int eggGrade = NUtil::GetEggGrade(pItem->GetData().quality);
		*pAck << static_cast<char>(eggGrade);
		*pAck << pItem->GetItemSeq();
	}

	pAck->MakePacket(CMD_SC_REQ_FAIRY_GACHYA);
	pUser->Send(pAck);


	// VC 처리
	if (1 == gachyaType)
	{
		// 인벤에서 뽑기인 경우 요청 갯수 만큼 처리
		for (int i = 0; i < gachyaCount; i++)
		{
			NLogic::NFunction::VCProcess(pUser, vcIndex);
		}
	}
	else if (2 == gachyaType)
	{
		// 샵에서 페어리 팩을 구매한 경우
		NLogic::NFunction::VCProcess(pUser, vcIndex);
	}
	else if (3 == gachyaType)
	{
		// 메일 뽑기인 경우 메일의 첨부 상태를 갱신
		pMail->GetData().gift_status = pMail->GetData().gift_status ^ EM_GIFT_ITEM;
		pMail->UpdateGiftStatusDatabaseMail();
	}
}

} /* NCommand */ } /* ProjectZ */
